﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PacketDotNet;
using SharpPcap;
using SharpPcap.LibPcap;
using System.IO;
using System.IO.Compression;
using System.Runtime.Serialization.Formatters.Binary;

namespace PcapDemo
{

    class Program
    {
        private static byte[] _sbytes = new byte[0];

        static HttpPacketPieceManager httpPacket = new HttpPacketPieceManager();

        static void Main(string[] args)
        {
            string ver = SharpPcap.Version.VersionString;
            LogHelper.Info("SharpPcap {0}", ver);


            //获取网络设备  
            var devices = LibPcapLiveDeviceList.Instance;
            if (devices.Count == 0)
            {
                LogHelper.Info("找不到网络设备");
                Console.ReadLine();
                return;
            }
            LogHelper.Info();
            LogHelper.Info("以下是目前本计算机上的活动网络设备:");
            LogHelper.Info("----------------------------------------------------");

            int i = 0;
            foreach (var p in devices)
            {
                LogHelper.Info("{0}: {1} ", i, p.Description);
                i = i + 1;
            }
            LogHelper.Info("-- 请选择一个需要监听的网络设备: ");
            i = Convert.ToInt32(Console.ReadLine());
            LibPcapLiveDevice device = devices[i];

            device.Open();
            device.OnPacketArrival += (s, e) =>
            {
                PcapPorcessContext(e.Packet);
            };

            //开始监听  
            device.StartCapture();

            //停止监听  
            Console.ReadLine();
            device.StopCapture();
            LogHelper.Info("-- 停止监听.");
            LogHelper.Info(httpPacket._httpPacketPieces.Count);
            foreach (var p in httpPacket._httpPacketPieces)
            {
                if (p.Psh)
                {
                    MessageAnalyse ma = new MessageAnalyse(p.Bytes);
                    LogHelper.Info("-------------------------------------------------" + p.Length);
                    LogHelper.Info(ma.GetMsg());
                }
            }
            LogHelper.Save("log.txt");
            Console.ReadLine();
        }

        static void PcapPorcessContext(RawCapture pPacket)
        {
            var time = pPacket.Timeval.Date;
            var len = pPacket.Data.Length;
            var layer = pPacket.LinkLayerType;

            LogHelper.Info("--------------------------------------------------");
            LogHelper.Info("{0} Len={1} Layer={2}",
                time.AddHours(8).ToString("HH:mm:ss"), len, layer);

            try
            {
                var packet = PacketDotNet.Packet.ParsePacket(layer, pPacket.Data);

                if (layer == PacketDotNet.LinkLayers.Ethernet) //以太网包  
                {
                    var ethernetPacket = (PacketDotNet.EthernetPacket)packet;
                    System.Net.NetworkInformation.PhysicalAddress srcMac = ethernetPacket.SourceHwAddress;
                    System.Net.NetworkInformation.PhysicalAddress destMac = ethernetPacket.DestinationHwAddress;

                    LogHelper.Info("MAC:{0} -> {1}", srcMac, destMac);
                    //LogHelper.Info("Ethernet packet: " + ethernetPacket);
                }

                //LogHelper.Info(packet.PrintHex());

                var ipPacket = packet.PayloadPacket as IpPacket; //IP包  
                if (ipPacket != null)
                {
                    System.Net.IPAddress srcIp = ipPacket.SourceAddress;
                    System.Net.IPAddress destIp = ipPacket.DestinationAddress;

                    LogHelper.Info("IP: {0} -> {1}", srcIp, destIp);
                    var tcpPacket = ipPacket.PayloadPacket as TcpPacket; //TCP包  
                    if (tcpPacket != null)
                    {
                        int srcPort = tcpPacket.SourcePort;
                        int destPort = tcpPacket.DestinationPort;

                        LogHelper.Info("TCP Port: {0} -> {1}", srcPort, destPort);
                        //LogHelper.Info("SequenceNumber:" + tcpPacket.SequenceNumber);
                        //LogHelper.Info("AcknowledgmentNumber:" + tcpPacket.AcknowledgmentNumber);
                        //LogHelper.Info("Checksum:" + tcpPacket.Checksum);
                        //LogHelper.Info("Psh:" + tcpPacket.Psh);
                        //LogHelper.Info("DataOffset:" + tcpPacket.DataOffset);
                        LogHelper.Info(tcpPacket.PrintHex());
                        var http = new HttpPacketPiece
                        {
                            SequenceNumber = tcpPacket.SequenceNumber,
                            AcknowledgmentNumber = tcpPacket.AcknowledgmentNumber,
                            Psh = tcpPacket.Psh,
                            SrcIp = ipPacket.SourceAddress,
                            DestIp = ipPacket.DestinationAddress,
                            Bytes = tcpPacket.PayloadData,
                            Length = tcpPacket.PayloadData.Length
                        };
                        httpPacket.Add(http);
                    }

                    var udpPacket = ipPacket.PayloadPacket as UdpPacket; //UDP包  
                    if (udpPacket != null)
                    {
                        int srcPort = udpPacket.SourcePort;
                        int destPort = udpPacket.DestinationPort;

                        LogHelper.Info("UDP Port: {0} -> {1}", srcPort, destPort);
                        LogHelper.Info(udpPacket.PrintHex());
                    }
                }
            }
            catch (Exception e)
            {
                LogHelper.Info(e.Message);
            }
        }
    }
}
